<template>
  <a-input v-model:value="comments" :title="comments" disabled>
    <template #addonAfter>
      <EditOutlined  @click="showModal" />
    </template>
  </a-input>
  <transition name="fade">
  <div class="container" v-show="local.show">
    <div style="margin: 10px 15px;">
      <div class="header">
        <span></span>
        <span class="close-btn">
          <CloseOutlined @click="closeModal" />
        </span>
      </div>
      <div class="input">
        <a-input v-model:value="local.inputString" placeholder="请输入待切分字符串" style="width: 100%;"/>
      </div>
      <div class="filter">
        <div class="con1" style="display: inline-block; width: calc( 50% - 2px )">
          <span>分隔符:</span>
          <a-select v-model:value="local.delimiter" :options="options" style="width: calc( 100% - 65px ); margin-left: 15px"/>
        </div>
        <div class="con2" style="display: inline-block; width: calc( 50% - 2px ); text-align: right">
          <span>去重:</span>
          <a-switch v-model:checked="local.dup" style="margin-left: 10px"/>
        </div>
      </div>
      <div class="list">
        <div class="s-head">
          <div class="s-head-left">
            <i :class="{checked:allChecked}" @click="checkAll"></i>
          </div>
          <div class="s-head-right">数据</div>
        </div>
        <ul class="s-body">
          <li v-for="(item, idx) in items" :key="idx">
            <div class="s-body-left" >
              <i :class="[item.checked?'checked':'']" @click="onCheck(item,idx)"></i>
            </div>
            <div class="s-body-right">
              <input type="text" class="item-input" v-model="item.value" />
            </div>
          </li>
        </ul>
      </div>
      <div class="footer-text">共 {{totalCount}} 条，当前选择 {{selectCount}} 条</div>
      <div class="footer-btns">
        <a-button @click="reset">清空</a-button>
        <a-button type="primary" @click="save">确定</a-button>
      </div>
    </div>
  </div>
  </transition>
</template>

<script lang="ts">
import {CloseOutlined, EditOutlined} from '@ant-design/icons-vue';
import {computed, reactive, watch} from "vue";

const DELIMITER = [
    {label:'换行符', value:'newline'},
    {label:'空格', value:'space'},
    {label:'逗号', value:'comma'},
    {label:'分号', value:'semicolon'},
    {label:'顿号', value:'day'},
];

const objMatch = [
  {type: '↵', match: 'newline'},
  {type: ' ', match: 'newline'},
  {type: ',', match: 'comma'},
  {type: '，', match: 'comma'},
  {type: '、', match: 'day'},
  {type: ';', match: 'semicolon'},
  {type: '；', match: 'semicolon'},
  {type: '|', match: 'delimiter'},
  {type: '｜', match: 'delimiter'}
];

const judgeDelimiter = (val)=>{
  let obj;
  let delimiter;
  for (let i = 0; i < objMatch.length; i++) {
    obj = objMatch[i];
    if(val.indexOf(obj.type) !== -1){
      delimiter = obj.match;
      break;
    }
  }
  if(typeof delimiter === 'undefined'){
    delimiter = 'comma';
  }
  return delimiter;
}

interface Item {
  checked: Boolean,
  value: String,
}

export default {
  name: "SeqSplitter",
  components:{
    EditOutlined, CloseOutlined
  },
  props:{
    value:{
      type: Array,
      default: ()=>([])
    }
  },
  emits:['update:value'],
  setup(props, {emit}){

    const local = reactive({
      show: false,
      inputString: '',
      delimiter:'',
      dup: true, // 去重

    });

    const items = reactive<Item[]>([]);

    const showModal = ()=>{
      local.show = true;
      local.delimiter = '';
    };

    const closeModal = ()=>{
      local.show = false;
    };

    const split = (val: string, delimiter: string):Item[] => {
      let xArr: string[] = [];
      if(val){
        let xValue = val;
        switch (delimiter) {
          case 'newline':
            if (xValue.indexOf('↵') !== -1) {
              xValue = xValue.replace(/↵/g, ' ')
            }
            xArr = xValue.split(' ');
            break;
          case 'space':
            xArr = xValue.split(' ');
            break;
          case 'comma':
            if (xValue.indexOf(',') !== -1) {
              xArr = xValue.split(',')
            } else {
              xArr = xValue.split('，')
            }
            break;
          case 'day':
            xArr = xValue.split('、');
            break;
          case 'semicolon':
            if (xValue.indexOf(';') !== -1) {
              xArr = xValue.split(';')
            } else {
              xArr = xValue.split('；')
            }
            break;
          case 'delimiter':
            if (xValue.indexOf('|') !== -1) {
              xArr = xValue.split('|')
            } else {
              xArr = xValue.split('｜')
            }
            break;
          default:
            break;
        }
      }
      return xArr.filter(x=>x.trim() !== '').map(x=>({checked:true,value:x}));
    };

    watch([()=>local.inputString, ()=>local.delimiter, ()=>local.dup], ([val, delimiter, dup])=>{
      let arr: Item[] = [];
      if(val){
        let separator = !delimiter ? judgeDelimiter(val):delimiter;
        arr = split(val, separator);
      }
      if(dup){
        arr = arr.filter(function(item,index,self){
          return self.findIndex(el=>el.value === item.value)===index;
        })
      }
      items.splice(0, items.length, ...arr);
    });

    const totalCount = computed(()=>items.length);
    const selectItems = computed(()=>items.filter(x=>x.checked));
    const selectCount = computed(()=>selectItems.value.length);
    const allChecked = computed(()=>{ return totalCount.value >0 && totalCount.value === selectCount.value});
    const comments = computed(()=>{
      const s = selectItems.value;
      if(s.length > 0){
        return s.map(x=>x.value).join('、').substring(0,20) + '... 共' +selectCount.value+ '条';
      } else {
        return ''
      }
    });


    const onCheck = (item)=>{
      item.checked = !item.checked;
    };

    const checkAll = ()=>{
      items.forEach(x=>x.checked = true);
    };

    const reset = ()=>{
      local.inputString = '';
    };

    const save = ()=>{
      const result = items.filter(x=>x.checked).map(x=>x.value);
      emit('update:value', result);
      local.show = false;
    };

    return {
      local,
      options: DELIMITER,
      items,
      showModal,
      closeModal,
      onCheck,
      checkAll,
      comments,
      totalCount,
      selectCount,
      allChecked,
      save,
      reset
    };
  }
}
</script>

<style scoped>

.container {
  background: #ffffff;
  width: 350px;
  border: none;
  padding: 0;
  font-size: 14px;
  position: absolute;
  z-index: 10000;
  box-sizing: border-box;
  border-radius: 2px;
  outline: 0;
  overflow-y: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .15 );
}

.header{
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  align-items: center;
}
.header .close-btn:hover{
  cursor: pointer;
  color: red;
}
.filter{
  padding: 15px;
}

.list {
  border: 1px solid #d9d9d9;
  line-height: 35px;
}

.s-head{
  padding: 0;
  height: 35px;
}
.s-head, .s-body{
  width: 100%;
}
.s-head-left,.s-head-right,.s-body-left,.s-body-right{
  display: inline-block;
  line-height: 35px;
  height: 35px;
  margin: 0;
  overflow:hidden;
}
.s-head-left,.s-body-left{
  width: 50px;
  border-right: 1px solid #d9d9d9;
  border-bottom: 1px solid #d9d9d9;
  text-align: center;
}
.s-head-right,.s-body-right{
  width: calc( 100% - 50px );
  border-bottom: 1px solid #d9d9d9;
  text-align: center;
}
.s-head-left i,.s-body-left i{
  display: block;
  width: 20px;
  height: 20px;
  margin: 8px auto;
  border:1px solid #d2d2d2;
  cursor: pointer;
}
.s-head-left i.checked,.s-body-left i.checked{
  background: url("") center no-repeat;
}

.s-body{
  height: 250px;
  padding: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.s-body li{
  height: 35px;
}
.s-body-left{

}

.item-input{
  border: none;
  width: 100%;
  height: 100%;
  padding-left: 10px;
  box-sizing: border-box;
}

.footer-text{
  height: 30px;
  line-height: 30px;
  text-align: right;
}
.footer-btns{
  padding: 5px 20px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

</style>
